# Lucid is (C) Copyright 2006-2007 by Infiscape Corporation
#
# This file is part of Lucid, a PyOpenSG example application.
#
# Lucid is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Lucid is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.

from PyQt4 import QtGui, QtCore
import console_view_base

import sys

import os.path
pj = os.path.join
sys.path.append( pj(os.path.dirname(__file__), '..', '..', '..'))
import lucid.core

import pycute3
import types
import inspect
import introspect

class ConsoleViewPlugin(lucid.core.IViewPlugin):
   def __init__(self):
      lucid.core.IViewPlugin.__init__(self)
      self.widget = ConsoleViewWidget(self)
      
   def getName():
      return "Console View"
   getName = staticmethod(getName)
      
   def getViewWidget(self):
      return self.widget
   
   def getIcon(self):
      return QtGui.QIcon(":/icons/data/icons/messages_16.png")
      
class Test:
   def test(self):
      pass

class ConsoleViewWidget(QtGui.QWidget, console_view_base.Ui_ConsoleViewBase):
   def __init__(self, locals=None, parent=None):
      QtGui.QWidget.__init__(self, parent)
      if locals is None:
         self.locals = {}
      else:
         self.locals = locals
      
      self.setupUi(self)

   def setupUi(self, widget):
      console_view_base.Ui_ConsoleViewBase.setupUi(self, widget)
      self.mConsole.hide()
      self.mRealConsole = pycute3.PyCute()
      self.mConsoleSplitter.insertWidget(0, self.mRealConsole)

      self.mRootItem = TreeItem("locals()", self.locals, self.mNamespaceTree)
      self.fillChildren(self.mRootItem)
      self.mNamespaceTree.addTopLevelItem(self.mRootItem)

      self.connect(self.mNamespaceTree, QtCore.SIGNAL("itemExpanded(QTreeWidgetItem*)"), self.onItemExpanded)
      self.connect(self.mNamespaceTree, QtCore.SIGNAL("itemCollapsed(QTreeWidgetItem*)"), self.onItemCollapsed)

   def onItemExpanded(self, item):
      print "Expand"
      for i in xrange(item.childCount()):
         self.fillChildren(item.child(i))

   def onItemCollapsed(self, item):
      print "Collapsed"
      for i in xrange(item.childCount()):
         item.child(i).takeChildren()

   def fillChildren(self, parent):
      d = getDict(parent.mData)
      for (lbl, data) in d.iteritems():
         item = TreeItem(lbl, data, parent)

class TreeItem(QtGui.QTreeWidgetItem):
   Type = QtGui.QTreeWidgetItem.UserType + 1

   def __init__(self, label, data, parent):
      QtGui.QTreeWidgetItem.__init__(self, parent, TreeItem.Type)
      self.mLabel = label
      self.mData = data

   def data(self, column, role):
      if QtCore.Qt.DisplayRole == role:
         return QtCore.QVariant(self.mLabel)
      else:
         return QtCore.QVariant()

COMMONTYPES = [getattr(types, t) for t in dir(types) \
               if not t.startswith('_') \
               and t not in ('ClassType', 'InstanceType', 'ModuleType')]

DOCTYPES = ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
            'FunctionType', 'GeneratorType', 'InstanceType',
            'LambdaType', 'MethodType', 'ModuleType',
            'UnboundMethodType', 'method-wrapper')

SIMPLETYPES = [getattr(types, t) for t in dir(types) \
               if not t.startswith('_') and t not in DOCTYPES]

del t

try:
    COMMONTYPES.append(type(''.__repr__))  # Method-wrapper in version 2.2.x.
except AttributeError:
    pass


def getDict(obj):
   """Return dictionary with attributes or contents of object."""
   otype = type(obj)
   if otype is types.DictType \
   or str(otype)[17:23] == 'BTrees' and hasattr(obj, 'keys'):
      return obj
   d = {}
   if otype is types.ListType or otype is types.TupleType:
      for n in range(len(obj)):
         key = '[' + str(n) + ']'
         d[key] = obj[n]
   if otype not in COMMONTYPES:
      for key in introspect.getAttributeNames(obj):
         # Believe it or not, some attributes can disappear,
         # such as the exc_traceback attribute of the sys
         # module. So this is nested in a try block.
         try:
            d[key] = getattr(obj, key)
         except:
            pass
   return d

if __name__ == "__main__":
   app = QtGui.QApplication(sys.argv)

   import __main__

   widget = ConsoleViewWidget(locals=__main__.__dict__)
   widget.show()
   sys.exit(app.exec_())
   
